package com.service.database.handler;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.common.utils.constant.Constants;
import com.common.utils.constant.SQLConstants;
import com.service.database.model.DataColumn;
import com.service.database.config.DataBase;
import com.service.database.constants.JdbcConstants;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.List;

/**
 * 数据库特殊操作类
 * @author xianggj
 * @Date 2021/6/4 21:41
 **/
public abstract class AbstractDatabaseHandler {

    public AbstractDatabaseHandler(DataBase type) {
        this.type = type;
        this.trchar = type.getTransferChar();
    }

    /**
     * 数据库名
     */
    protected DataBase type;
    /**
     * 转义符
     */
    protected String trchar;

    /**
     * 链接符号
     */
    protected String linkStr = JdbcConstants.QUESTION_MARK;

    /**
     * 数据库名
     */
    protected String dbName;

    /**
     * 模式名称
     */
    protected String schema;

    /**
     * 用户名
     */
    protected String userName;

    /**
     * 密码
     */
    protected String pwd;

    /**
     * 表名
     */
    protected String tableName;

    /**
     * 列信息
     */
    protected String[] cols;

    /**
     * 主键
     */
    protected String columnKey;

    protected String[] returnKeys;

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }

    public void setSchema(String schema) {
        this.schema = schema;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public void setCols(String... cols) {
        if (cols != null && cols.length > 0){
            for (int i = 0; i < cols.length; i++) {
                cols[i] = addChar(cols[i]);
            }
        }
        this.cols = cols;
    }

    public void setColumnKey(String columnKey) {
        this.columnKey = columnKey;
    }

    public void setReturnKeys(List<String> keys) {
        keys.stream().forEach(k->{
            this.returnKeys = ArrayUtil.append(returnKeys, addChar(k));
        });
    }

    /**
     * url特殊处理
     * @return
     */
    public abstract String urlSpecialDeal(StringBuffer currentUrl);

    /**
     * 查询数据库sql
     * @return
     */
    public abstract String getShowDataBaseSql();

    /**
     * 查询数据表
     * @return
     */
    public abstract String getShowTablesSql();

    /**
     * 查询数据库表详情sql
     * @return
     */
    public abstract String getShowTableDescSql();

    /**
     * 查询数据库表数据sql
     * @return
     */
    public abstract String getShowTableDataSql();

    /**
     * 查询数据库表数据数量sql
     * @return
     */
    public abstract String getShowTableDataNumSql();

    /**
     * 查询数据库表数据指定列并去重
     * @return
     */
    public abstract String distinctColSql();

    /**
     * 删除表sql
     * @return
     */
    public abstract String dropTableSql();

    /**
     * 创建表sql
     * @return
     */
    public abstract List<String> createTableSql(List<DataColumn> columns);

    /**
     * 查询数据库表数据指定列并去重
     * @return
     */
    public abstract String addLimitBySql(String sql , Integer num, Integer offset);

    /**
     * 谈及转义符
     * @param str
     * @return
     */
    protected String addChar(String str){
        return trchar + str + trchar;
    }


    protected abstract String intToType(int i);

    /**
     * 添加转义符
     * @param str
     * @param escape
     * @return
     */
    public String addEscape(String str, String escape){
        if (StrUtil.contains(str, escape)){
            return str;
        } else {
            return escape + str + escape;
        }
    }


    /**
     * 生成创建语句
     * @return
     */
    public String createInsertSQL() {
        StringBuffer insertSql = new StringBuffer(SQLConstants.INSERT_INFO);
        insertSql.append(addEscape(tableName, trchar));
        insertSql.append(SQLConstants.LEFT_BRACKET);
        for (int i = 0; i < cols.length ; ++i) {
            if (i > 0){
                insertSql.append(SQLConstants.COMMA);
            }
            insertSql.append(addEscape(cols[i], trchar));
        }
        insertSql.append(SQLConstants.RIGHT_BRACKET);
        insertSql.append(SQLConstants.VALUES);
        insertSql.append(SQLConstants.LEFT_BRACKET);
        String[] array = new String[cols.length];
        Arrays.fill(array, SQLConstants.QUESTION);
        insertSql.append(StringUtils.join(array, Constants.COMMA));
        insertSql.append(SQLConstants.RIGHT_BRACKET);
        return insertSql.toString();
    }

    /**
     * 生成覆盖语句
     * 每个数据库不一样 慎用
     * @return
     */
    public String createReplaceSQL() {
        StringBuffer insertSql = new StringBuffer(SQLConstants.REPLACE_INFO);
        insertSql.append(addEscape(tableName, trchar));
        insertSql.append(SQLConstants.LEFT_BRACKET);
        for (int i = 0; i < cols.length ; ++i) {
            if (i > 0){
                insertSql.append(SQLConstants.COMMA);
            }
            insertSql.append(addEscape(cols[i] , trchar));
        }
        insertSql.append(SQLConstants.RIGHT_BRACKET);
        insertSql.append(SQLConstants.VALUES);
        insertSql.append(SQLConstants.LEFT_BRACKET);
        String[] array = new String[cols.length];
        Arrays.fill(array, SQLConstants.QUESTION);
        insertSql.append(StringUtils.join(array, Constants.COMMA));
        insertSql.append(SQLConstants.RIGHT_BRACKET);
        return insertSql.toString();
    }
    /**
     * 生成修改语句
     * @return
     */
    public String createUpdateSQL() {
        //UPDATE `test`.`test` SET `name` = 'a', `age` = 1 WHERE `id` = 1;
        StringBuffer insertSql = new StringBuffer(SQLConstants.UPDATE);
        insertSql.append(addEscape(tableName, trchar));
        insertSql.append(SQLConstants.SET);
        for (int i = 0; i < cols.length - 1; ++i) {
            if (i > 0) {
                insertSql.append(SQLConstants.COMMA);
            }
            insertSql.append(addEscape(cols[i], trchar));
            insertSql.append(SQLConstants.EQ);
            insertSql.append(SQLConstants.QUESTION);

        }
        insertSql.append(SQLConstants.WHERE);
        insertSql.append(addEscape(columnKey, trchar));
        insertSql.append(SQLConstants.EQ);
        insertSql.append(SQLConstants.QUESTION);

        return insertSql.toString();
    }
}
